Wafer roughness plot
1 Base function
1.1 Different \(\mu\) sampling points
Code
# 1. Read the Excel file into a DataFrame
df = pd.read_excel('data/base_function.xlsx', sheet_name=['base', 'M'])
# 2. Split the DataFrame into two separate DataFrames
base_df = df['base']
M_df = df['M'].sort_values(by='M')
# M_df = M_df[~M_df.isin([-0.002, 0.003]).any(axis=1)]
sorted_df = pd.DataFrame(columns=['mu','xaxis', 'yaxis', 'colors'])
# 3. Create x axis
xaxis = np.arange(-15.5, 16.5, 1)
plots = []
# 4. Iterate M dataframe
for i, (index, row) in enumerate(M_df.iterrows()):
# a. Plot raw sampling data
p = figure(title=str(f'M: {row.M}'), x_axis_label='sampling point', y_axis_label='intensity', tooltips = [("index", "$index"),("(x,y)", "($x, $y)")],
width = 250, height = 150)
new_axis = xaxis - row.M
p.line(new_axis, base_df[index], line_color='#9DD9C5', line_width=3)
p.circle(new_axis, base_df[index], size = 4)
vline = Span(location=0.0, dimension = 'height', line_color='#FEEED9', line_width=1)
p.add_layout(vline)
# b. Plot format
p.x_range = Range1d(-7, 7)
p.yaxis.ticker.desired_num_ticks = 4
p = plot_format(p, "Degrees", "Intensity", "bottom_left", "8pt", "8pt", "8pt")
plots.append(p)
# c. Create dataframe
sorted_df = sorted_df.append(pd.DataFrame({'mu':[row.M]*32,'xaxis':new_axis, 'yaxis':base_df[index], 'colors':new_colors[0:32]}), ignore_index=True)
grid_raw = gridplot(children = plots, ncols = 6, merge_tools=False)
show(grid_raw)1.2 Base function smoothing and interpolation
Code
# 5. Create interleaved plots
interleaved_plot = figure(title='Interleaved base function', x_axis_label='sampling point', y_axis_label='intensity', tooltips = [("index", "$index"),("(x,y)", "($x, $y)")],
width = 700, height = 500)
smooth_plot = figure(title='Smooth base function', x_axis_label='sampling point', y_axis_label='intensity', tooltips = [("index", "$index"),("(x,y)", "($x, $y)")],
width = 700, height = 500)
interpolated_plot = figure(title='Inteporlated base function points', tooltips = [("index", "$index"),("(x,y)", "($x, $y)")],
width = 700, height = 500)
# a. Define base_function and smooth df's
base_function_df = sorted_df.sort_values(by='xaxis')
diff = base_function_df['xaxis'].diff()
smooth_df = base_function_df[(diff >= 0.01) | (diff.isna())]
smooth_df = smooth_df.iloc[1:]
# b. Create non-smooth and smoot curve
interleaved_plot = figure(title='Interleaved base function', x_axis_label='sampling point', y_axis_label='intensity', tooltips=[("index", "$index"), ("(x,y)", "($x, $y)")],
width=700, height=500)
smooth_plot = figure(title='Smooth base function', x_axis_label='sampling point', y_axis_label='intensity', tooltips=[("index", "$index"), ("(x,y)", "($x, $y)")],
width=700, height=500)
# c. Plot points
for (plot, df, legend, color) in [(interleaved_plot, base_function_df, 'Non-smooth base function', '#9DC3E6'), (smooth_plot, smooth_df, 'Smooth base function', '#9D6C97')]:
# individual points
plot.circle(df.xaxis, df.yaxis, color=df.colors, size=6)
# smooth curve
plot.line(df['xaxis'], df['yaxis'], line_width=4, legend=legend, color=color)
# format
plot.xaxis.ticker.desired_num_ticks = 15
plot.y_range = Range1d(0, 45000)
plot = plot_format(plot, "Degrees", "Intensity", "top_left", "10pt", "10pt", "9pt")
# d. Interpolation
x_base = np.arange(-15.5, 15.5001, 0.001)
pchip = PchipInterpolator(smooth_df['xaxis'], smooth_df['yaxis'])
y_base = pchip(x_base)
interpolated_plot.line(x=smooth_df['xaxis'], y=smooth_df['yaxis'], line_width = 5, legend = 'Smooth base function', color = '#9D6C97')
interpolated_plot.line(x_base, y_base, line_width = 5, color = '#9DD9C5', legend = 'Interpolated base function')
interpolated_plot.xaxis.ticker.desired_num_ticks = 15
interpolated_plot.y_range = Range1d(0, 45000)
interpolated_plot = plot_format(interpolated_plot, "Degrees", "Intensity", "top_left", "10pt", "10pt", "9pt")
base_function_grid = gridplot(children=[interleaved_plot, smooth_plot, interpolated_plot], ncols=3, merge_tools=False, width=420, height=350)
show(base_function_grid)2 Rough data
Code
# This function takes an array of x values (x) and three additional parameters: a, b, and c. The a parameter scales the output of the base_function, while the b and c parameters control the shape of the fitted function. By multiplying the output of base_function by a, we can adjust the amplitude of the fitted function to match the data. The b and c parameters allow us to adjust the position and width of the fitted function to better match the data.
# When we call curve_fit, we pass in the fit_function along with the xdata and ydata arrays. The curve_fit function then adjusts the a, b, and c parameters to minimize the difference between the fitted function and the data. The function returns two values: the optimal parameter values (in the params variable), and an estimate of the covariance matrix (in the _ variable, which we ignore in this example).
# Once we have the optimal parameter values, we can evaluate the fitted function at any set of x values using:Code
from scipy.optimize import curve_fit
# Define base function using xinterp and yinterp
def base_function(x, *params):
return np.interp(x, x_base, y_base)
# Define function to fit to dataset1
def fit_function(x, a, b, c):
return a * base_function(x, b, c)
# Extract xaxis and yaxis from dataset1
rough_df = pd.read_excel('data/rough_samples.xlsx')
xdata = rough_df['xaxis']
ydata = rough_df['pt2e']
# Use curve_fit to find parameters that minimize the difference between the data and the model
params, _ = curve_fit(fit_function, xdata, ydata)
# Evaluate the fitted function using the optimal parameters
yfit = fit_function(x_base, *params)
fit_plot = figure(title='Fit plot', x_axis_label='sampling point', y_axis_label='intensity', tooltips = [("index", "$index"),("(x,y)", "($x, $y)")],
width = 700, height = 500)
fit_plot.line(x_base, y_base, line_width = 5, color = '#9DD9C5')
# fit_plot.line(x_base, yfit, line_width = 4, color = '#9D6C97', line_dash="dotdash")
fit_plot.line(xdata, ydata, line_width = 5, color = '#9DC3E6')
fit_plot.circle(xdata, ydata, size = 8, color = '#9DC3E6', fill_color='#2F528F')
fit_plot = plot_format(fit_plot, "Degrees", "Intensity", "top_left", "10pt", "10pt", "9pt")
show(fit_plot)Code
def fit_function(x, a):
return a * base_function(x)
from scipy.optimize import curve_fit
xdata = rough_df['xaxis']
ydata = rough_df['pt2e']
params, _ = curve_fit(fit_function, xdata, ydata)
yfit = fit_function(x_base, *params)
fit_plot = figure(title='Fit plot', x_axis_label='sampling point', y_axis_label='intensity', tooltips = [("index", "$index"),("(x,y)", "($x, $y)")],
width = 700, height = 500)
fit_plot.line(x_base, y_base, line_width = 4, color = '#9DD9C5', legend = 'Base function', line_dash=[10, 5])
fit_plot.line(x_base, yfit, line_width = 4, color = '#9D6C97', legend = 'pt2 fitted function', line_dash="dotdash")
fit_plot.line(xdata, ydata, line_width = 5, color = '#9DC3E6', legend_label = 'pt2 line')
fit_plot.circle(xdata, ydata, size = 10, color = '#9DC3E6', fill_color='#2F528F', legend_label = 'pt2 points')
fit_plot = plot_format(fit_plot, "Degrees", "Intensity", "top_left", "10pt", "10pt", "9pt")
show(fit_plot)Code
from bokeh.palettes import Set3
# 1. Import data
rough_df = pd.read_excel('data/rough_samples.xlsx')
source_rough = ColumnDataSource(rough_df)
# # 2. Create plot
rough_plot = figure(x_axis_label='xaxis', y_axis_label='yaxis', width = 650, height = 400, tooltips = [("index", "$index"),("(x,y)", "($x, $y)")])
color_palette = Set3[len(rough_df.columns[1:])+1]
# a. iterate over the columns and add a line for each one
for i, col in enumerate(rough_df.columns[1:]):
rough_plot.line('xaxis', col, source=source_rough, color = color_palette[i], legend_label = str(col), line_width=4)
rough_plot.circle('xaxis', col, source=source_rough, color = color_palette[i], size=6)
rough_plot.line(x_base, y_base, line_width=4, color = color_palette[i+1], legend = 'Interpolated base function')
rough_plot = plot_format(rough_plot, "Degrees", "Intensity", "top_left", "10pt", "10pt", "10pt")
show(rough_plot)3 Wafer 2 with rough areas
3.1 Calcute Aq, M and I values
Code
lendata = data.shape[0] - 1
angles = (np.linspace(0, (lendata - 1), lendata)) * (data[-1, 29] - data[-1, 28]) * (2 * np.pi / lendata / 360) + (data[-1, 28] + 9.5 + 180) * np.pi / 180
radii = (np.linspace(0, (lendata-1), lendata)) * (data[-1,31]-data[-1,30])/lendata + data[-1, 30]
Aq = []
M = []
intens = []
x = np.arange(1, 33)
datamat = data[:lendata,:] - 1
sx = np.arange(1, 32, 0.2)
for indx in range(lendata):
# a. Do PChip spline interpolation
diodes = datamat[indx,:]
pchip = PchipInterpolator(x, diodes)
sy = pchip(sx)
sy = 100 * sy / np.max(sy)
c = []
# b. Concatenation/histogram
for indx2 in range(len(sx)):
c.extend([indx2+1]*round(sy[indx2]))
stddev = np.std(c) / 5
Aq.append(1.02 * np.exp(1.987 * np.log(stddev) + 0.16))
M.append((np.mean(c) - 1) / 5 - 15.5)
intens.append(np.sum(sy))3.2 Non interpolated Plot
Code
# 1. Get x and y coordinates
xvals = radii * np.cos(angles) * 1e-3
yvals = radii * np.sin(angles) * 1e-3
zvals = Aq
# 2. Clamp values to max of 3
zvalscut = 3
zvalsnew = np.array(zvals)
zvalsnew[zvalsnew > zvalscut] = zvalscut
# 3. Make a df
index = np.arange(len(xvals))
df = pd.DataFrame({
'index':index,
'x': xvals*1000,
'y': yvals*1000,
'z': zvalsnew,
})
#| column: screen-inset-right
# 4. Rank_text
interval = alt.selection_interval()
rank_text = alt.Chart(df).mark_text(dx=20, dy=-5, align='left').encode(
x=alt.value(10), # x position of the text
y=alt.value(10), # y position of the text
text=alt.condition(
interval,
alt.Text('index:Q', format='.2f'), # display 'x' column for selected points
alt.value('') # display empty string for unselected points
),
color=alt.value('black'), # color of the text
fontSize = 5
)
# 5. Wafer plot
wafer_plot = alt.Chart(df).mark_circle().encode(
x='x:Q', y='y:Q',
color=alt.condition(
interval,
alt.Color('z:Q', scale=alt.Scale(scheme='turbo')),
alt.value('lightgray')
),
tooltip=['x', 'y', 'z', 'index']
).properties(height=400, width=400).add_selection(interval)
# create a table with the selected points
selected_points_table = alt.Chart(df).transform_filter(
interval
).mark_text().encode(
x=alt.value(0),
y=alt.Y('row_number:O', axis=None),
text='index:Q',
).transform_window(
row_number='row_number()'
).properties(
height=400,
width=50
)
# vertically concatenate the two charts
alt.hconcat(wafer_plot, selected_points_table)
Code
sorted_df